import numpy as np
import itertools
from utils2 import JS_D

def fuzzy_boundary_classifying(predicted_label, reference_label, boundary_range=0.05):
    data_num = len(predicted_label)
    correct_num = 0
    for i in range(data_num):
        if predicted_label[i] == reference_label[i]: # 如果当前预测标签和参考标签一致，则认为分类正确
            correct_num += 1
            continue
        start = i # 当前参考标签从索引哪一帧开始的
        end = i # 当前参考标签在哪一帧结束
        cur_reference_label = reference_label[i]
        last_label = 0 # 上一个参考标签
        next_label = 0 # 下一个参考标签
        while True: # 找到当前参考标签从哪一帧开始
            if reference_label[start - 1] == cur_reference_label:
                start -= 1
            else:
                last_label = reference_label[start - 1]
                break
        while True: # 找到当前参考标签在哪一帧结束
            if reference_label[(end + 1) % data_num] == cur_reference_label: 
                end += 1
            else:
                next_label = reference_label[(end + 1) % data_num]
                break
        
        if (i - start) / (end - start) < boundary_range and predicted_label[i] == last_label: # 如果当前帧位于两种标签的交界处附近，且被预测标签为相邻的参考标签，则认为正确分类
            correct_num += 1
            continue

        if (end - i) / (end - start) < boundary_range and predicted_label[i] == next_label: # 如果当前帧位于两种标签的交界处附近，且被预测标签为相邻的参考标签，则认为正确分类
            correct_num += 1
            continue

    return correct_num / data_num

def get_classify_acc(predicted_label, reference_label, boundary_range=0.05):
    predicted_label = np.array(predicted_label)
    label_num = len(set(predicted_label))
    label_names = list(range(label_num))
    permutations = list(itertools.permutations(label_names, label_num))
    accs = []
    for label_mapping in permutations:
        rearranged_predicted_label = predicted_label.copy()
        for i in label_names:
            rearranged_predicted_label[predicted_label == i] = label_mapping[i]
        accs.append(fuzzy_boundary_classifying(rearranged_predicted_label, reference_label, boundary_range=boundary_range))
    # print(accs)
    return max(accs)

def get_scp(all_frame_ds, typical_scene_idxes):
    frame_num = np.shape(all_frame_ds)[0]
    straight_typical_scene_ds = all_frame_ds[typical_scene_idxes[0]]
    turn_typical_scene_ds     = all_frame_ds[typical_scene_idxes[1]]
    alert_typical_scene_ds    = all_frame_ds[typical_scene_idxes[2]]

    straight_scp = []
    turn_scp = []
    alert_scp = []

    for i in range(frame_num):
        cur_ds = all_frame_ds[i]
        js_s = JS_D(cur_ds, straight_typical_scene_ds)
        js_t = JS_D(cur_ds, turn_typical_scene_ds)
        js_a = JS_D(cur_ds, alert_typical_scene_ds)
        if js_s < js_t and js_s < js_a:
            straight_scp.append(cur_ds)
        elif js_t < js_s and js_t < js_a:
            turn_scp.append(cur_ds)
        else:
            alert_scp.append(cur_ds)

    straight_scp = np.average(np.array(straight_scp), axis=0)
    turn_scp =  np.average(np.array(turn_scp), axis=0)
    alert_scp =  np.average(np.array(alert_scp), axis=0)

    return straight_scp, turn_scp, alert_scp